#include "cmd.h"

#ifdef ENV_SUPPORT
#include "var.h"
#endif

CMD cmdtable[] = {
	{"ver", do_ver, man_ver},
	{"help", do_help, man_help},
	{"shell", do_shell, man_shell},
	{"quit", do_quit, man_quit},
#ifdef ENV_SUPPORT
	{"setenv", do_setenv, man_setenv},
	{"saveenv", do_saveenv, man_saveenv},
	{"unsetenv", do_unsetenv, man_unsetenv},
	{"printenv", do_printenv, man_printenv},
#endif
	{"label", do_label, man_label},
	{"format", do_format, man_format},
	{"cd", do_cd, man_cd},
	{"dir", do_dir, man_dir},
	{"mkdir", do_mkdir, man_mkdir},
	{"rmdir", do_rmdir, man_rmdir},
	{"type", do_type, man_type},
	{"copy", do_copy, man_copy},
	{"del", do_del, man_del},
};

static char *argv[PARAM_MAXARGS + 1];
static char cmdbuf[CMD_BUF_SIZ];

/* Visual C++ doesn't have internal isblank(). */
#if _WIN32
static int isblank (int c)
{
	if (c == ' ')
		return 1;
	return 0;
}
#endif

/*
** make_argv() from U-boot 
*/
static int make_argv(char *s, int argvsz, char *argv[])
{
	int argc = 0;

	/* split into argv */
	while (argc < argvsz - 1) {

		/* skip any white space */
		while (isblank(*s))
			++s;

		if (*s == '\0') /* end of s, no more args       */
			break;

		argv[argc++] = s;       /* begin of argument string     */

		/* find end of string */
		while (*s && !isblank(*s))
			++s;

		if (*s == '\0')         /* end of s, no more args       */
			break;

		*s++ = '\0';            /* terminate current arg         */
	}
	argv[argc] = NULL;

	return argc;
}

static void show_prompt(void)
{
#ifdef ENV_SUPPORT
	Var *pvar = find_var("PROMPT");
	if (pvar)
		printf("%s> ", pvar->var_value);
	else
		printf("%s> ", CMD_PROMPT);	
#else
	printf("%s> ", CMD_PROMPT);
#endif
}

CMD* find_cmd(CMD* pcmd, char *inbuf)
{
	CMD *p = cmdtable;
	int i = sizeof(cmdtable) / sizeof(CMD);

	while(p && (i-- > 0)) {
		if(strncmp(inbuf, p->name, strlen(p->name)) == 0) {
			p->argc = make_argv(inbuf, sizeof(argv) / sizeof(argv[0]), argv);
			p->argv = argv;
			return p;
		} else {
			p++;
		}
	}

	return NULL;
}

void show_cmds(void)
{
	CMD *p = cmdtable;
	int i = sizeof(cmdtable) / sizeof(CMD);	

	while (p && (i-- > 0)) {
		printf("%s\n", p->name);
		p++;
	}
}

char *get_cmd(void)
{
	if (fgets(cmdbuf, CMD_BUF_SIZ - 1, stdin))
		cmdbuf[strlen(cmdbuf) - 1] = '\0';
	return cmdbuf;
}

int run_cmd(CMD* pcmd)
{
	if(pcmd)
		return pcmd->func(pcmd->argc, pcmd->argv);
	else
		return ERR_CMD_NOT_FOUND;
}

int show_manual(char *cmdstr)
{
	CMD* pcmd = find_cmd(cmdtable, cmdstr);
	if (pcmd) {
		pcmd->man();
		return ERR_CMD_OK;
	}
	else
		return ERR_CMD_NOT_FOUND;
}

void cmd_loop(void)
{
	int ret;

#ifdef ENV_SUPPORT
	init_var();
#endif

	while(!QuitFlag) {
		show_prompt();

		if(get_cmd() == NULL) {
			printf("Quit\n");
			return;
		}

		ret = run_cmd(find_cmd(cmdtable, cmdbuf));
		if(ret == 0)
			printf("-OK-\n");
		else
			printf("-ERR: %d-\n", ret);
	}

}
